#include "bsp.h"
#include "gd32e23x.h"
#include "systick.h"

static void _bsp_rcc_initial(void)
{
	systick_config();
}

static void _bsp_gpio_initial(void)
{
	do {
		rcu_periph_clock_enable(LCM_RST_GPIO_CLK);

		gpio_mode_set(LCM_RST_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCM_RST_PIN);
		gpio_output_options_set(LCM_RST_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCM_RST_PIN);
		GPIO_BC(LCM_RST_GPIO_PORT) = LCM_RST_PIN;
	} while (0);

	do {
		rcu_periph_clock_enable(LT9211_RST_GPIO_CLK);

		gpio_mode_set(LT9211_RST_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LT9211_RST_PIN);
		gpio_output_options_set(LT9211_RST_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LT9211_RST_PIN);
		GPIO_BC(LT9211_RST_GPIO_PORT) = LT9211_RST_PIN;
	} while (0);

	/* GPIO IN */
	do {
		rcu_periph_clock_enable(LT9211_INT_GPIO_CLK);
		rcu_periph_clock_enable(RCU_CFGCMP);

		gpio_mode_set(LT9211_INT_GPIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, LT9211_INT_PIN);
	} while (0);

	/* UART */
	do {
		/* enable COM GPIO clock */
		rcu_periph_clock_enable(RCU_GPIOA);

		/* connect port to USARTx_Tx */
		gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_2);

		/* connect port to USARTx_Rx */
		gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_3);

		/* configure USART Tx as alternate function push-pull */
		gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2);
		gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_2);

		/* configure USART Rx as alternate function push-pull */
		gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3);
		gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_3);
	} while (0);

	/* EXTI */
	do {
		/* pin2, PF0 exti*/
		rcu_periph_clock_enable(RCU_GPIOF);
		/* configure button pin as input */
		gpio_mode_set(GPIOF, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0);

		/* pin10, PA4 exti*/
		rcu_periph_clock_enable(RCU_GPIOA);
		/* configure button pin as input */
		gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_4);

	} while (0);
}

static void _bsp_uart_initial(void)
{
	/* enable USART clock */
	rcu_periph_clock_enable(RCU_USART1);

	/* USART configure */
	usart_deinit(USART1);
	usart_word_length_set(USART1, USART_WL_8BIT);
	usart_stop_bit_set(USART1, USART_STB_1BIT);
	usart_parity_config(USART1, USART_PM_NONE);
	usart_baudrate_set(USART1, 115200U);
	usart_receive_config(USART1, USART_RECEIVE_ENABLE);
	usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);

	usart_enable(USART1);
}

static void _bsp_i2c_initial(void)
{
	rcu_periph_clock_enable(I2C0_SCL_GPIO_CLK);
	gpio_mode_set(I2C0_SCL_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C0_SCL_PIN);
	gpio_output_options_set(I2C0_SCL_GPIO_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C0_SCL_PIN);
	GPIO_BOP(I2C0_SCL_GPIO_PORT) = I2C0_SCL_PIN;

	rcu_periph_clock_enable(I2C0_SDA_GPIO_CLK);
	gpio_mode_set(I2C0_SDA_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C0_SDA_PIN);
	gpio_output_options_set(I2C0_SDA_GPIO_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C0_SDA_PIN);
	GPIO_BOP(I2C0_SDA_GPIO_PORT) = I2C0_SDA_PIN;
}

static void _bsp_esd_gpio_initial(void)
{
	/* enable the CFGCMP clock */
	rcu_periph_clock_enable(RCU_CFGCMP);
	/* enable and set key EXTI interrupt to the specified priority */
	nvic_irq_enable(EXTI0_1_IRQn, 0U);
	nvic_irq_enable(EXTI4_15_IRQn, 0U);

	/* connect key EXTI line to key GPIO pin */
	syscfg_exti_line_config(EXTI_SOURCE_GPIOF, EXTI_SOURCE_PIN0);
	syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN4);

	/* configure key EXTI line */
	exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_RISING);
	exti_interrupt_flag_clear(EXTI_0);
	exti_init(EXTI_4, EXTI_INTERRUPT, EXTI_TRIG_RISING);
	exti_interrupt_flag_clear(EXTI_4);
}

void bsp_initial(void)
{
	_bsp_rcc_initial();
	_bsp_gpio_initial();
	_bsp_uart_initial();
	_bsp_i2c_initial();
	_bsp_esd_gpio_initial();
}

void bsp_gpio_write_lt9211_rst(int v)
{
	if (v != 0) {
		gpio_bit_write(LT9211_RST_GPIO_PORT, LT9211_RST_PIN, SET);
	} else {
		gpio_bit_write(LT9211_RST_GPIO_PORT, LT9211_RST_PIN, RESET);
	}
}

void bsp_gpio_write_driver_rst(int v)
{
	if (v != 0) {
		gpio_bit_write(LCM_RST_GPIO_PORT, LCM_RST_PIN, SET);
	} else {
		gpio_bit_write(LCM_RST_GPIO_PORT, LCM_RST_PIN, RESET);
	}
}

void bsp_uart_send(const char *buff, int size)
{
	for (int i = 0; i < size; i++) {
		usart_data_transmit(USART1, buff[i]);
		while (RESET == usart_flag_get(USART1, USART_FLAG_TBE))
			;
	}
}
